//============================================================================
// Name        : Buffer.cpp
// Author      : Artur Taranyuk
// Version     :
// Copyright   : Your copyright notice
// Description : Buffer#include <iostream>
//============================================================================

#include "Buffer.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <malloc.h>
#include <errno.h>

using namespace std;



Buffer::Buffer(const char * const filename, const char * const output) {

	openCode = open(filename, O_SYNC, O_DIRECT);
		if (openCode > 0) {
		//printf("Open Input succeeded.\n");
		} else {
			printf("Open Input failed.\n");
			switch(errno) {
            	case EACCES: printf ("Buffer ERROR: Permission denied.\n"); break;
                case EMFILE: printf ("Buffer ERROR: No file handle available.\n"); break;
                case ENOENT: printf ("Buffer ERROR: File or path not found.\n"); break;
                default: printf ("Buffer ERROR: Unknown error.\n"); break;
            }
        }
	openCode1 = open(output, O_RDWR | O_CREAT, S_IRWXU);
	if (openCode1 > 0) {
	} else {
	       //printf("Open Output failed.\n");
	       	   switch(errno) {
	           	   case EACCES: printf ("Buffer ERROR: Permission denied.\n"); break;
	               case EMFILE: printf ("Buffer ERROR: No file handle available.\n"); break;
	               case ENOENT: printf ("Buffer ERROR: File or path not found.\n"); break;
	               //default: printf ("Buffer ERROR: Unknown error.\n"); break;
	           }
		}
	pagesize = getpagesize();
	alloc();

}
Buffer::~Buffer() {

}

void Buffer::alloc() {
	int fehler = posix_memalign((void**) &buffer1, pagesize, pagesize);
	if (fehler > 0) {
	}
	int fehler2 = posix_memalign((void**) &buffer2, pagesize, pagesize);
	if (fehler2 > 0) {
	}
	int fehler3 = posix_memalign((void**) &outputBuffer, pagesize, pagesize);
	if (fehler3 > 0) {
	}
	loadPuffer1();
	next = buffer1;
	base = buffer1;
	InputNext = outputBuffer;
	count = 0;
}

int Buffer::getchar() {

	if (*next == EOF) {
		if (buffer1[4095] == EOF) {
			loadPuffer2();
			next = buffer2;
			buffer1[4095] = 0;
		} else if (buffer2[4095] == EOF) {
			loadPuffer1();
			next = buffer1;
			buffer2[4095] = 0;
		} else {
			return EOF;

		}
	}
	output = *next;
	next++;
	//cout<<output;
	return output;
}

void Buffer::ungetchar(size_t times) {
	while (times>0){
	if (next == &buffer2[0]) {
		next = &buffer1[4094];
		buffer1[4095]=EOF;
		next++;
	} else if (next == &buffer1[0]) {
		next = &buffer2[4094];
		buffer2[4095]=EOF;
		next++;
	}
	next--;
	times--;
	}
}

void Buffer::loadPuffer1() {
	int Actual = 1;
	int Max = 4095;
	Actual = read(openCode, buffer1, Max);
	if (Actual == 4095) {
		buffer1[4095] = EOF;
	}
	if ((Actual < Max) & (Actual > 0)) {
		buffer1[Actual] = EOF;

	}
}

void Buffer::loadPuffer2() {
	int Actual = 1;
	int Max = 4095;
	Actual = read(openCode, buffer2, Max);
	if (Actual == 4095) {
		buffer2[4095] = EOF;
	}
	if ((Actual < Max) & (Actual > 0)) {
		buffer2[Actual] = EOF;
	}
}
/*
void Buffer::lexemAcceped() {
	next++;
	base = next;
}
*/
void Buffer::putchar(char value) {

	*InputNext = value;
	InputNext++;
	count++;
	if (count == 4096) {
		writeFile();
	}
}

void Buffer::writeFile() {
	int more = 1;
	int maximum = 4096;
	more = write(openCode1, outputBuffer, count);
	cout << more;
	if (more < maximum) {
	}
	InputNext = outputBuffer;
	count = 0;
}

void Buffer::close(){
	writeFile();
}
